package com.ruoyi.wwxkf.service.impl;

import cn.hutool.core.util.StrUtil;
import com.ruoyi.utils.contast.WxxContast;
import com.ruoyi.utils.model.fastgpt.FastGPTRequest;
import com.ruoyi.utils.wwx.WwxMsgUtil;
import com.ruoyi.utils.wwx.WwxNetWorkUtil;
import com.ruoyi.utils.wxmsg.AesException;
import com.ruoyi.utils.wxmsg.WXBizMsgCrypt;
import com.ruoyi.wwxkf.domain.WxMsgRevice;
import com.ruoyi.wwxkf.service.WwxKfNotifyService;
import com.ruoyi.wwxkf.service.WwxKfService;
import com.ruoyi.wwxkf.vo.WwxKfConfigVO;
import com.ruoyi.wwxkf.vo.WwxSyncMsg;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class WwxKfNotifyServiceImpl implements WwxKfNotifyService {
    @Autowired
    private WwxKfService wwxKfService;
    @Autowired
    public RedisTemplate redisTemplate;

    public WwxKfConfigVO getWwConfigInfo() {
        WwxKfConfigVO wwxKfConfigVO = new WwxKfConfigVO();
        wwxKfConfigVO.setToken("n6Q2g2pM9jibXIfeEvemIQb3BiLb");
        wwxKfConfigVO.setCorpID("ww381c803ff4e460b9");
        wwxKfConfigVO.setEncodingAESKey("NktHfdrgEDP2MJw5IIj55WMSD5pjiSdkqgyzsmwi57D");
        return wwxKfConfigVO;
    }

    /**
     * 处理回调信息
     */
    @Override
    public String notifyMsg(String msgSignature, String timestamp, String nonce, String echostr, String xmlData) {
        try {
            String idempotentRedisKey = msgSignature + timestamp;
            Boolean ishave = redisTemplate.hasKey(idempotentRedisKey);
            if (ishave) {
                log.error("幂等性校验，消息时间：{}，已经在处理了，进入了处理", timestamp);
                return "error";
            } else {
                redisTemplate.opsForValue().set(msgSignature + timestamp, true);
                if (StrUtil.isNotBlank(echostr)) {
                    return verifyCallBackUrl(msgSignature, timestamp, nonce, echostr);
                } else {
                    return catchMsgRevice(msgSignature, timestamp, nonce, xmlData);
                }
            }

        } catch (AesException e) {
            log.error("处理回调消息时发生异常", e);
            throw new RuntimeException("处理回调消息时发生异常", e);
        }
    }

    /**
     * 配置回调参数信息验证 验证回调url
     */
    private String verifyCallBackUrl(String msgSignature, String timestamp, String nonce, String echostr) throws AesException {
        log.info("验证配置的回调参数，msgSignature：{}，timestamp{}，nonce{}，echostr：{}", msgSignature, timestamp, nonce, echostr);
        try {
            WwxKfConfigVO wwConfigInfo = getWwConfigInfo();
            String corpID = wwConfigInfo.getCorpID();
            String token = wwConfigInfo.getToken();
            String encodingAESKey = wwConfigInfo.getEncodingAESKey();
            WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(token, encodingAESKey, corpID);
            return wxBizMsgCrypt.VerifyURL(msgSignature, timestamp, nonce, echostr);
        } catch (AesException e) {
            log.error("认证失败:{}", e.getMessage());
            throw new RuntimeException("认证失败：" + e.getMessage());
        }

    }

    /**
     * 处理事件回调，包含消息等
     */
    private String catchMsgRevice(String msgSignature, String timestamp, String nonce, String xmlData) throws AesException {
        if (StrUtil.isBlank(xmlData)) {
            log.error("需要解密的消息为空");
            throw new IllegalArgumentException("需要解密的消息为空");
        }
        WwxKfConfigVO wwConfigInfo = getWwConfigInfo();
        String corpID = wwConfigInfo.getCorpID();
        String token = wwConfigInfo.getToken();
        String encodingAESKey = wwConfigInfo.getEncodingAESKey();
        WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(token, encodingAESKey, corpID);
        // 解密消息
        String decryptMsg = wxBizMsgCrypt.DecryptMsg(msgSignature, timestamp, nonce, xmlData);
        // 如果需要被动回复消息，构造响应包
        String encryptMsg = wxBizMsgCrypt.EncryptMsg(decryptMsg, timestamp, nonce);
        log.info("回调函数返回消息：{}", encryptMsg);
        //处理收到消息后的操作
        //1：获取到具体的消息
        WwxSyncMsg wwxSyncMsg = doActionForMsg(decryptMsg);
        String msgtype = wwxSyncMsg.getMsgtype();
        return encryptMsg;
    }

    /**
     * 获取到消息后对消息处理
     *
     * @param decryptMsg
     */
    public WwxSyncMsg doActionForMsg(String decryptMsg) {
        log.info("处理接收到的消息");
        WxMsgRevice wxMsgRevice = WwxMsgUtil.DecryptMsgParse(decryptMsg);
        String accessToken = wwxKfService.getAccessToken();
        String cursor = getCursor();
        //获取到具体的消息回答
        Integer origin = 3; //  消息来源。3-微信客户发送的消息 4-系统推送的事件消息 5-接待人员在企业微信客户端发送的消息
        WwxSyncMsg wwxSyncMsg = WwxNetWorkUtil.syncMsg(accessToken, wxMsgRevice, cursor, origin);

        String msgtype = wwxSyncMsg.getMsgtype();
        /**
         * 只接受文本消息
         */
        if (StrUtil.equals(msgtype, "text")) {
            catchDigTextMsg(accessToken, wwxSyncMsg);
        } else {

        }
        //TODO 将本条消息存放到数据库

        return wwxSyncMsg;
    }

    /**
     * 文本类消息
     *
     * @param wwxSyncMsg
     * @return
     */
    public void catchDigTextMsg(String accessToken, WwxSyncMsg wwxSyncMsg) {
        String content = wwxSyncMsg.getText().getContent();
        if (StrUtil.isNotBlank(content)) {
            String replayContent = FastGPTRequest.requestAiMessage(content, wwxSyncMsg);
            WwxNetWorkUtil.sendMsgText(accessToken, wwxSyncMsg, replayContent);

            //当发送了预约消息则发送这些内容
            if (StrUtil.contains(content, "预约") || StrUtil.contains(content, "联系")) {
                String externalUserid = wwxSyncMsg.getExternal_userid();
                String contentKfKey = WxxContast.IS_CAN_CONTANT_KF_KEY + externalUserid;
                Boolean isHave = redisTemplate.hasKey(contentKfKey);
                if (!isHave) {
                    String randomCaLink = getRandomCaLink(externalUserid);
                    WwxNetWorkUtil.sendMsgGetCustom(accessToken, wwxSyncMsg, randomCaLink);
                    WwxNetWorkUtil.sendMsgText(accessToken, wwxSyncMsg, "这是我们的客服老师,您有疑问可以添加我们的客服老师\uD83D\uDE0A");
                    //设置该用户2个小时不再发送客服老师
                    redisTemplate.opsForValue().set(contentKfKey, true, 2, TimeUnit.HOURS);
                }

            }
        }
    }


    /**
     * 获取绘会话记录点，要不获取全部的对话
     */
    public String getCursor() {
        //TODO 将这个数据存入到数据库
        return null;
    }

    /**
     * 随机获取获客链接
     */
    public String getRandomCaLink(String externalUserid) {
        // 定义链接列表
        List<String> links = Arrays.asList(
                "https://work.weixin.qq.com/ca/cawcde82e5b42263c8",
                "https://work.weixin.qq.com/ca/cawcde6ef389c1e9be",
                "https://work.weixin.qq.com/ca/cawcded3662751c99f",
                "https://work.weixin.qq.com/ca/cawcdee232c81e5ce0",
                "https://work.weixin.qq.com/ca/cawcdea050894a8d9d"
        );
        // 生成Redis键
        String redisKey = WxxContast.GET_CALINK_KEY + externalUserid;

        // 从Redis中获取缓存链接
        Object cachedLink = redisTemplate.opsForValue().get(redisKey);

        // 如果缓存中存在链接，直接返回
        if (cachedLink != null) {
            return (String) cachedLink;
        }

        // 缓存中不存在链接，随机选择一个
        String randomLink = links.get(new Random().nextInt(links.size()));

        // 将随机链接存入Redis，有效期24小时
        redisTemplate.opsForValue().set(redisKey, randomLink, 24, TimeUnit.HOURS);

        // 返回随机链接
        return randomLink;
    }


}
